package service

import (
	"gorm.io/gorm"
	"shop-bean/constant"
	"shop-bean/dto"
	"shop-bean/model"
	"shop-bean/request"
	"shop-common/library/loggerV2"
	"shop-common/library/variables"
	"shop-common/utils/uploader"
	"shop-service/repository"
	"strings"
)

type IPictureService interface {
	Put(uint, uint, *uploader.FileRequest) (*uploader.FileResponse, error)
	Move(request *request.AttachmentRequest, oldDb *model.Attachment) error
	DeleteBatch(rows []*model.Attachment) error
	FindAttIds(attIds []uint) ([]*dto.AttachmentDTO, error)
	UpdateBatchStatus(fileIds []uint, state int) error
}

type PictureService struct {
	db         *gorm.DB
	repository repository.IPictureRepository
}

func NewPictureService() IPictureService {
	return &PictureService{
		db:         variables.GormDB(),
		repository: repository.NewPictureRepository(),
	}
}

/**
 * 图片上传
 * @param multipartFile 文件
 * @param model 模块 用户user,商品product,微信wechat,news文章
 * @param pid 分类ID 0编辑器,1商品图片,2拼团图片,3砍价图片,4秒杀图片,5文章图片,6组合数据图,7前台用户,8微信系列
 * @return FileResultVo uploaderStorage
 */
func (s *PictureService) Put(userId uint, pid uint, validFile *uploader.FileRequest) (*uploader.FileResponse, error) {
	vo, err := uploader.GetDefaultStorage().Put(validFile)
	if err != nil {
		loggerV2.Error(err)
		return nil, err
	}

	entity := &model.Attachment{
		AttId:       0,
		UserId:      userId,
		RealName:    vo.RealName,
		Name:        vo.Name,
		AttDir:      vo.AttDir,
		AttSize:     vo.AttSize,
		AttType:     vo.AttType,
		ContentType: vo.ContentType,
		Pid:         pid,
		ImageType:   vo.LocationType,
		Key:         vo.Key,
		Hash:        vo.Hash,
		Bucket:      vo.Bucket,
		Status:      constant.ATTACHMENT_FILE_NORMAL,
	}

	err = s.repository.Create(s.db, entity)

	if err != nil {
		loggerV2.Error(err)
		return nil, err
	}

	return &uploader.FileResponse{
		Status:         uploader.FileSuccess,
		FileId:         entity.AttId,
		Path:           validFile.NewFileName,
		Name:           validFile.NewFileName,
		Url:            strings.Join([]string{uploader.GetHostStatic(vo.LocationType), vo.AttDir, vo.Name}, ""),
		Code:           0,
		FileFormerName: vo.RealName,
	}, nil
}

func (s *PictureService) Move(request *request.AttachmentRequest, attDb *model.Attachment) error {
	var count int64
	err := variables.GormDB().Model(&model.Attachment{}).Select("att_id").
		Where("name = ?", request.Name).Where("image_type = ?", attDb.ImageType).Count(&count).Error
	if err != nil {
		loggerV2.Error(err)
		return err
	}

	if count > 0 {
		return err
	}

	_, err = uploader.GetManualStorage(attDb.ImageType).Move(attDb.AttDir+uploader.ReplaceFilename(attDb.Name), attDb.AttDir+uploader.ReplaceFilename(request.Name))
	if err != nil {
		loggerV2.Error(err)
		return err
	}

	err = s.db.Model(&model.Attachment{}).Where("att_id = ?", request.AttId).Update("name", request.Name).Error
	if err != nil {
		loggerV2.Error(err)
		return err
	}

	return nil
}

func (s *PictureService) DeleteBatch(rows []*model.Attachment) error {
	var attIds []uint
	var qiniuFilePath []string
	var localFilePath []string
	for _, row := range rows {
		attIds = append(attIds, row.AttId)
		if row.ImageType == uploader.LOCAL_TYPE_ATTACHMENT {
			localFilePath = append(localFilePath, row.AttDir+row.Name)
		} else if row.ImageType == uploader.QINIU_TYPE_ATTACHMENT {
			qiniuFilePath = append(qiniuFilePath, row.Name)
		}
	}

	err := s.repository.DeleteBatch(s.db, attIds)
	if err != nil {
		loggerV2.Error(err)
		return err
	}

	if localFilePath != nil && len(localFilePath) > 0 {
		err = uploader.GetManualStorage(constant.LOCAL_TYPE_ATTACHMENT).BucketDelete(localFilePath...)
	}

	if qiniuFilePath != nil && len(qiniuFilePath) > 0 {
		err = uploader.GetManualStorage(constant.QINIU_TYPE_ATTACHMENT).BucketDelete(qiniuFilePath...)
	}

	return nil
}

func (s *PictureService) FindAttIds(attIds []uint) (list []*dto.AttachmentDTO, err error) {
	rows, err := s.repository.FindInFullColumn(s.db, attIds)
	if err != nil {
		return nil, err
	}
	for _, row := range rows {
		list = append(list, &dto.AttachmentDTO{
			AttId:       row.AttId,
			RealName:    row.RealName,
			Name:        row.Name,
			Url:         strings.Join([]string{uploader.GetHostStatic(row.ImageType), row.AttDir, row.Name}, ""),
			AttSize:     row.AttSize,
			AttType:     row.AttType,
			ContentType: row.ContentType,
			Pid:         row.Pid,
			ImageType:   row.ImageType,
		})
	}
	return list, nil
}

func (s *PictureService) UpdateBatchStatus(fileIds []uint, state int) error {
	if err := s.repository.UpdateBatchStatus(s.db, fileIds, state); err != nil {
		loggerV2.Errorf("updateBatch attacheFile status failed:  %v, files: %s, state: %d", err, fileIds, state)
		return err
	}
	return nil
}
